package com.hsgene.common.util.date;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 时间日期格式解析
 *
 * @author wangbing
 * @version 1.0, 2018/07/10
 */
public class TimeJsonDeserializer extends JsonDeserializer<Date> {

    private static final Logger logger = LogManager.getLogger(TimeJsonDeserializer.class);

    /**
     * 匹配 2018-08-24T17:35:50.000+0800 格式的日期时间
     * <p>
     * PS：此处只用来匹配字符串符合的日期时间解析Pattern，具体位置上的数字是否超限不做检查，由SimpleDateFormat在转换时做检查，下同。
     * </p>
     */
    private static final String YYYY_MM_DD_T_HH_MM_SS_SSSZ_REGEX = "\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}(\\+|-)\\d{4}";

    /**
     * 匹配 2018-09-03 13:54:53 格式的日期时间
     */
    private static final String YYYY_MM_DD_HH_MM_SS_REGEX = "\\d{4}-\\d{2}-\\d{2} \\d{2}:\\d{2}:\\d{2}";

    /**
     * 匹配 2018-09-03 格式的日期
     */
    private static final String YYYY_MM_DD_REGEX = "\\d{4}-\\d{2}-\\d{2}";

    @Override
    public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
            throws IOException {
        if (jsonParser == null || StringUtils.isEmpty(jsonParser.getText())) {
            return null;
        }

        try {
            String value = jsonParser.getValueAsString();
            logger.info("解析日期时间：{}", value);
            SimpleDateUtils.DatePattern pattern = matchPattern(value);
            if (pattern == null) {
                logger.error("暂不支持的日期时间格式解析：{}", value);
                return null;
            }
            return SimpleDateUtils.parseDate(value, pattern.toString());
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    private static SimpleDateUtils.DatePattern matchPattern(String value) {
        if (matchISOPattern(value)) {
            return SimpleDateUtils.DatePattern.ISO_PATTERN;
        } else if (matchStandardPattern(value)) {
            return SimpleDateUtils.DatePattern.STANDARD_PATTERN;
        } else if (matchOnlyDatePattern(value)) {
            return SimpleDateUtils.DatePattern.YYYY_MM_DD;
        } else {
            return null;
        }
    }

    public static boolean matchStandardPattern(String value) {
        Matcher matcher = Pattern.compile(YYYY_MM_DD_HH_MM_SS_REGEX).matcher(value);
        return matcher.matches();
    }

    private static boolean matchISOPattern(String value) {
        Matcher matcher = Pattern.compile(YYYY_MM_DD_T_HH_MM_SS_SSSZ_REGEX).matcher(value);
        return matcher.matches();
    }

    private static boolean matchOnlyDatePattern(String value) {
        Matcher matcher = Pattern.compile(YYYY_MM_DD_REGEX).matcher(value);
        return matcher.matches();
    }
}
